//
//  BaseWorld.cpp
//  IsoCplus
//
//  Created by zhouzhanglin on 15/9/17.
//
//

#include "BaseWorld.h"
#include "VisibleRect.h"
#include "iso/IsoGridLine.h"

USING_NS_CC;

bool BaseWorld::init()
{
    if(!BaseWorld::init(GRID_SIZE, GRID_X, GRID_Z)) return false;
    return true;
}

bool BaseWorld::init(unsigned int size, unsigned int spanX, unsigned int spanZ){
    if(!IsoWorld::init(size, spanX, spanZ)) return false;
    
    _gridData = new PathGrid();
    _gridData->init(GRID_X,GRID_Z);
    _gridData->setAllWalkable(true);
    
    Rect r = VisibleRect::getVisibleRect();
    setPosition(r.size.width/2-MAP_WIDTH/2,r.size.height+150);
    panSceneLayerTo(MAP_WIDTH/2-20,-320 );
    
    _endX = getPositionX();
    _endY = getPositionY();
    
    return true;
}

void BaseWorld::onEnter()
{
    IsoWorld::onEnter();
    
    //添加背景图片
    auto bg = Sprite::create("isoRes/Background.png");
    bg->setAnchorPoint(Vec2(0,1));
    bg->setScale(2,2);
    setBg(bg);
    
    //添加网格.
    auto gridNode = new IsoGridLine();
    gridNode->init(GRID_SIZE,GRID_X,GRID_Z,100);
    addScene(gridNode);
    gridNode->render();
    gridNode->autorelease();
    
    auto listener = EventListenerTouchAllAtOnce::create();
    listener->onTouchesBegan = CC_CALLBACK_2(BaseWorld::onTouchesBegan, this);
    listener->onTouchesMoved = CC_CALLBACK_2(BaseWorld::onTouchesMoved, this);
    listener->onTouchesEnded = CC_CALLBACK_2(BaseWorld::onTouchesEnded, this);
    listener->onTouchesCancelled = CC_CALLBACK_2(BaseWorld::onTouchesEnded, this);
    
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    
    schedule(CC_SCHEDULE_SELECTOR(BaseWorld::update));
}


void BaseWorld::update(float dt)
{
    auto speed = 1.0/60*_moveSpeed;
    setPosition(getPositionX()+(_endX-getPositionX())*speed,getPositionY()+(_endY-getPositionY())*speed);
}


void BaseWorld::onTouchesBegan(const std::vector<Touch*> &touches, Event*evt)
{
    for(int i=0;i<touches.size();i++)
    {
        auto touch = touches[i];
        auto tid = touch->getID();
        auto point = touch->getLocation();
        MyTouch myt(point,point,point,"began",tid) ;
        _touches.push_back(myt);
    }
    if(_touches.size()==1){
        _moveSpeed=40;
        _beganWorldX = getPositionX();
        _beganWorldY = getPositionY();
        _endX = _beganWorldX;
        _endY = _beganWorldY;
    }
}
void BaseWorld::onTouchesMoved(const std::vector<Touch*> &touches, Event* evt)
{
    for(int i=0;i<touches.size();i++)
    {
        auto touch = touches[i];
        auto tid = touch->getID();
        auto point = touch->getLocation();
        auto prevPoint = touch->getPreviousLocation();
        
        for(int j=0;j<_touches.size();j++){
            auto v = _touches[j];
            if(v.tid==tid){
                v.current = point;
                v.prev = prevPoint;
                v.type = "moved";
            }
            _touches[j] = v;
        }
    }
    if(_touches.size()==1){
        auto deltaX = _touches[0].current.x-_touches[0].began.x;
        auto deltaY = _touches[0].current.y-_touches[0].began.y;
        _endX = _beganWorldX+deltaX;
        _endY = _beganWorldY+deltaY;
        modifyEndPosition();
    }else if(_touches.size()>1){
        
        //中点
        auto middleX = (_touches[0].began.x+_touches[1].began.x)/2;
        auto middleY = (_touches[0].began.y+_touches[1].began.y)/2;
        
        auto currentVector = _touches[0].current - _touches[1].current ;
        auto previousVector = _touches[0].prev - _touches[1].prev;

        //scale
        auto sizeDiff = currentVector.length()/ previousVector.length();
        if (VisibleRect::getVisibleRect().size.height>640) {
            sizeDiff = sizeDiff > 1 ?  1 + (sizeDiff - 1) * 1.4 : 1 - (1 - sizeDiff) * 1.4;
        }
        
        if(sizeDiff<1){
            if(getScaleX()>1){
                scaleWorld(sizeDiff,middleX,middleY);
            }
        }else if(sizeDiff>1){
            if(getScaleY()<2.5){
                scaleWorld(sizeDiff,middleX,middleY);
            }
        }
    }
    
}
void BaseWorld::onTouchesEnded(const std::vector<Touch*> &touches, Event* evt)
{
    auto len = touches.size();
    if(len==0) return;

    for(int i=0;i<len;i++){
        auto touch = touches[i];
        auto tid = touch->getID();
        auto point = touch->getLocation();
        for(int j=0;j<_touches.size();j++){
            auto v = _touches[j];
            if(v.tid==tid){
                v.current = point;
                v.type = "ended";
            }
            _touches[j] = v;
        }
    }
    
    if(_touches.size()==1){
        auto dis = _touches[0].current.distance(_touches[0].began);
        if(dis>10){
            _moveSpeed = 5;
            _endX = _endX + (_touches[0].current.x-_touches[0].prev.x)*6/getScaleX();
            _endY = _endY + (_touches[0].current.y-_touches[0].prev.y)*6/getScaleY();
            modifyEndPosition();
        }else if(dis<10){
            //点击
            auto pos = pixelPointToGrid(_touches[0].current.x,_touches[0].current.y);
            onClick(pos);
        }
    }
    _touches.clear();
}



void BaseWorld::scaleWorld(float sizeDiff,float middleX,float middleY)
{
    _scaleMatrix.identity();
    _scaleMatrix.scale(getScaleX(),getScaleY());
    _scaleMatrix.translate(getPositionX(),getPositionY());
    _scaleMatrix.tx = _scaleMatrix.tx - middleX;
    _scaleMatrix.ty = _scaleMatrix.ty - middleY;
    
    _scaleMatrix.scale(sizeDiff,sizeDiff);
    
    _scaleMatrix.tx = _scaleMatrix.tx + middleX;
    _scaleMatrix.ty = _scaleMatrix.ty + middleY;
    
    setScaleX(_scaleMatrix.a);
    setScaleY(_scaleMatrix.d);
    
    setPosition(_scaleMatrix.tx,_scaleMatrix.ty);
  
    _endX = _scaleMatrix.tx;
    _endY = _scaleMatrix.ty;
    
    Rect rt = VisibleRect::getVisibleRect();
    if(_endY<rt.size.height){
        _endY=rt.size.height;
        setPositionY(rt.size.height );
    }else if(_endY > MAP_HEIGHT*getScaleY()){
        _endY = MAP_HEIGHT*getScaleY();
        setPositionY(_endY);
    }
    
    if(_endX>0){
        _endX=0;
        setPositionX(0);
    }else if(_endX<-MAP_WIDTH*getScaleX()+rt.size.width){
        _endX = -MAP_WIDTH*getScaleX()+rt.size.width;
        setPositionX(_endX);
    }
}

void BaseWorld::modifyEndPosition()
{
    Rect rt = VisibleRect::getVisibleRect();
    if (_endY<rt.size.height) _endY=rt.size.height;
    else if(_endY>MAP_HEIGHT*getScaleY()) _endY = MAP_HEIGHT*getScaleY();
    
    if (_endX>0) _endX=0;
    else if(_endX<-MAP_WIDTH*getScaleX()+rt.size.width)
        _endX = -MAP_WIDTH*getScaleX()+rt.size.width;
}

